package com.producer.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 公共线程池配置
 *
 * @author Liunh
 */
@Slf4j
@Configuration
@EnableAsync
public class ThreadAsyncConfigurer implements AsyncConfigurer {

    @Value("${spring.task.execution.thread-name-prefix:thread_name_prefix_}")
    private String threadNamePrefix;
    @Value("${spring.task.scheduling.pool.size:8}")
    private int corePoolSize;
    @Value("${spring.task.execution.pool.max-size:128}")
    private int maxPoolSize;
    @Value("${spring.task.execution.pool.queue-capacity:200}")
    private int queueCapacity;
    @Value("${spring.task.execution.pool.keep-alive:600}")
    private int keepAliveSeconds;

    private int awaitTerminationMillis = 120;

    private boolean waitForJobsToCompleteOnShutdown = Boolean.TRUE;


    @Bean(name = "taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        final ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(corePoolSize);
        threadPool.setMaxPoolSize(maxPoolSize);
        threadPool.setQueueCapacity(queueCapacity);
        threadPool.setWaitForTasksToCompleteOnShutdown(waitForJobsToCompleteOnShutdown);
        threadPool.setAwaitTerminationSeconds(awaitTerminationMillis);
        threadPool.setKeepAliveSeconds(keepAliveSeconds);
        threadPool.setThreadNamePrefix(threadNamePrefix);
        threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        threadPool.initialize();
        return threadPool;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncExceptionHandler();
    }

    /**
     * 自定义异常处理类
     *
     * @author liunh
     */
    static class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
            log.info(">>>>>> SysAsyncExecutor Exception! Method name - {}, message - {}", method.getName(), throwable.getMessage());
            for (Object param : obj) {
                log.info(">>>>>> SysAsyncExecutor Exception Parameter value - " + param);
            }
        }
    }


}
